/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 */

 #include "log.hpp"
 #include <hilog/log.h>
 #include <cstdio>
 #include <vector>
 #include <cstdarg>
 
 namespace {
 constexpr unsigned int FRAMEGENERATION_DOMAIN = 0xD005810;
 constexpr size_t SHORT_STRING_OPTIMIZATION = 256U;
 } // end of anonymous namespace
 
 void Log::Report(Priority prio, const char *format, ...) noexcept
 {
     char shortString[SHORT_STRING_OPTIMIZATION];
     std::vector<char> bigString{};
     char *str = shortString;
 
     va_list argumentPtr;
     va_start(argumentPtr, format);
 
     // 使用标准 vsnprintf 替换 vsnprintf_s
     int needed = vsnprintf(shortString, SHORT_STRING_OPTIMIZATION, format, argumentPtr);
     
     // 检查是否需要更大的缓冲区
     if (needed < 0) {
         // 格式化失败，使用默认错误消息
         va_end(argumentPtr);
         constexpr LogLevel const cases[] = {LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR};
         OH_LOG_Print(LOG_APP, cases[static_cast<size_t>(prio)], FRAMEGENERATION_DOMAIN, "VulKanFG", 
                     "%{public}s", "Log formatting failed");
         return;
     }
     
     if (static_cast<size_t>(needed) >= SHORT_STRING_OPTIMIZATION) {
         // 需要更大的缓冲区
         size_t bufferSize = static_cast<size_t>(needed) + 1U;
         bigString.resize(bufferSize);
         str = bigString.data();
         
         // 重新开始 va_list 因为上面的 vsnprintf 可能已经消费了它
         va_end(argumentPtr);
         va_start(argumentPtr, format);
         
         int ret = vsnprintf(str, bufferSize, format, argumentPtr);
         if (ret < 0) {
             // 第二次格式化也失败了
             va_end(argumentPtr);
             constexpr LogLevel const cases[] = {LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR};
             OH_LOG_Print(LOG_APP, cases[static_cast<size_t>(prio)], FRAMEGENERATION_DOMAIN, "VulKanFG", 
                         "%{public}s", "Log formatting failed");
             return;
         }
     }
 
     va_end(argumentPtr);
 
     constexpr LogLevel const cases[] = {LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR};
     OH_LOG_Print(LOG_APP, cases[static_cast<size_t>(prio)], FRAMEGENERATION_DOMAIN, "VulKanFG", "%{public}s", str);
 }